namespace Stee.CAP8.MessageBus.Sagas.Core.Extensions
{

    using Microsoft.Extensions.DependencyInjection;
    using Stee.CAP8.MessageBus.Interface.Interfaces;
    using Stee.CAP8.MessageBus.Kafka.Publisher;
    using Stee.CAP8.MessageBus.Kafka.Subscriber;
    using Stee.CAP8.MessageBus.Sagas.Core.Attributes;
    using Stee.CAP8.MessageBus.Sagas.Core.Bus;
    using Stee.CAP8.MessageBus.Sagas.Core.Ioc;
    using Stee.CAP8.MessageBus.Sagas.Core.Sagas;
    using Stee.CAP8.MessageBus.Sagas.Core.Storages.Dtos;
    using Stee.CAP8.MessageBus.Sagas.Core.Storages.Nodes;
    using Stee.CAP8.MessageBus.Sagas.Core.Storages.Steps;
    using System;
    using System.Linq;
    using System.Reflection;

    public static class EventBusExtension
    {

     

        public static IServiceCollection AddSagaMiddleware(this IServiceCollection services)
           
        {

            services.AddSingleton<IBus, EventBus>();
            services.AddTransient<IPublisher, PublisherImpl>();
            services.AddTransient<ISubscriber, SubscriberImpl>();
            services.AddSingleton<ISagaStepStorage, InMemorySagaStepStorage>();
            services.AddSingleton<ISagaNodeStorage, InMemorySagaNodeStorage>();

            services.AddSingleton<ISagaProcessHistoryStorage, InMemorySagaProcessHistoryRepository>();
            var alltypes = Assembly.GetCallingAssembly().GetTypes();

            var typeHandle = typeof(BaseMainSaga<>);
            var implementSagaList = alltypes.Where(x => x.IsSubClassOfRawGeneric(typeHandle)).ToList();




            implementSagaList.ForEach(type =>
            {
                 var attr = Attribute.GetCustomAttribute(type, typeof(SagaTopicAttribute), inherit: true);
                if (attr != null)
                {
                    var topicAttrib = attr as SagaTopicAttribute;
                    Ioc.SagaContainer.SagaTopicInfos.Add(topicAttrib.Topic, type);
                }
                services.AddTransient(type);
                Console.WriteLine("注册成功" + type.FullName);

            });
            var provider = services.BuildServiceProvider();
            SagaContainer.ServiceProvider = provider;
            return services;
        }


        public static IServiceCollection UseSaga(this IServiceCollection services, Action<IBus> busAction)
        {
            var provider = services.BuildServiceProvider();

            var bus = provider.GetService<IBus>();

            busAction?.Invoke(bus);

            return services;
        }



    }
}
